#include <stdio.h>
#include <stdint.h>
#include <string.h>

#define DERR        0   /* error */
#define DWAN        1   /* warning */
#define DINF        2   /* information */
#define DNOT        3   /* note */
#define DBUG        4   /* debug */
#define DIGN        5   /* ignore */

/**
 * dmsg: debug message
 * dlog: debug log
 */
#define dmsg(lvl, fmt, arg...)  if(lvl <= dlvl) {                                                   \
                                    printf(fmt, ##arg);                                             \
                                }

#define dlog(lvl, fmt, arg...)  if(lvl <= dlvl) {                                                   \
                                    printf("[%04d][%s] "fmt"\r\n", __LINE__, __FUNCTION__, ##arg);  \
                                }

int dlvl = DBUG;

/* 
        
        
   AA   
  A  A  
 A    A 
 A    A 
 A    A 
 A    A 
 A    A 
 A    A 
 A    A 
  A  A  
   AA   
        
        
-------------------------------------
        
        
   XX   
  XAAX  
 XAXXAX 
XAX  XAX
XAX  XAX
XAX  XAX
XAX  XAX
XAX  XAX
XAX  XAX
XAX  XAX
 XAXXAX 
  XAAX  
   XX   
        
-------------------------------------
        
        
   XX   
  X  X  
 X XX X 
X X  X X
X X  X X
X X  X X
X X  X X
X X  X X
X X  X X
X X  X X
 X XX X 
  X  X  
   XX   
        
*/

#define HOLLOW_MARK1            'A'
#define HOLLOW_MARK2            'X'
#define HOLLOW_MARK3            ' '

/* gray 一维为行, 二维为列 */
/**
 * @brief 点阵字模转化为灰度字模(灰度图片)
 * @note  点阵字模, 一个bit表示一个显示像素
 * @note  灰度字模, 一个Byte表示一个显示像素, 可以简单理解为灰度图片
 */
int hollow_dot2gray(uint32_t width, uint32_t height, uint8_t *dot, uint8_t *gray)
{
    int i = 0;                  // 用于遍历点阵字模的每一个byte
    int j = 0;                  // 用于遍历byte中的每一个bit
    int byte_total = 0;         // 字模总共有多少个byte
    int byte_per_column = 0;    // 字模一列有多少个byte
    
    /* 扫描方式决定这里的计算方法, (阴码-逐列-逆向) */
    byte_per_column = (height + 7) / 8;
    byte_total = width * byte_per_column;
    dlog(DBUG, "byte_per_column = %d", byte_per_column);
    dlog(DBUG, "byte_total      = %d", byte_total);

    for(i = 0; i < byte_total; i++)
    {
        for(j = 0; j < 8; j++)
        {       
            int x = (i % byte_per_column) * 8 + j;              // x表示点阵字模的行号, 从上至下递增
            int y = i / byte_per_column;                        // y表示点阵字模的列号, 从做至右递增
            dlog(DIGN, "(%2d, %2d)", x, y);
            
            /* 强行使用一维数组当做二维数组来用, 是因为二维数组作为函数参数需要指定第二维的元素个数 */
            gray[x * width + y] = dot[i] & (0x1 << j) ? HOLLOW_MARK1 : HOLLOW_MARK3;
        }
    }

    return 0;
}

/**
 * @brief 灰度字模(灰度图片)转化为点阵字模
 * @note  灰度字模, 一个Byte表示一个显示像素, 可以简单理解为灰度图片
 * @note  点阵字模, 一个bit表示一个显示像素
 */
int hollow_gray2dot(uint32_t width, uint32_t height, uint8_t *gray, uint8_t *dot)
{
    int x = 0;                  // x表示点阵字模的行号, 从上至下递增
    int y = 0;                  // y表示点阵字模的列号, 从做至右递增
    int byte_total = 0;         // 字模总共有多少个byte
    int byte_per_column = 0;    // 字模一列有多少个byte

    /* 清空点阵字模数据 */
    /* 扫描方式决定这里的计算方法, (阴码-逐列-逆向) */
    byte_per_column = (height + 7) / 8;
    byte_total = width * byte_per_column;
    memset(dot, 0, byte_total);

    for(x = 0; x < height; x++)
    {
        for(y = 0; y < width; y++)
        {
            if(HOLLOW_MARK2 == gray[x * width + y])
            {
                dot[y * byte_per_column + x / 8] |= 1 << (x % 8);
            }
        }
    }

    return 0;
}

/**
 * @brief 灰度字模添加边框
 * @note  灰度字模, 一个Byte表示一个显示像素
 */
int hollow_border_add(uint32_t width, uint32_t height, uint8_t *gray)
{
    int i;

    for(i = 0; i < width * height; i++)
    {
        if(gray[i] == HOLLOW_MARK1)
        {
            int x = i / width;
            int y = i % width;
            
            // 上
            if(x > 0)
            {
                if(gray[(x - 1) * width + y] != HOLLOW_MARK1)
                {
                    gray[(x - 1) * width + y] = HOLLOW_MARK2;
                }
            }
            
            // 下
            if(x < (height - 1))
            {
                if(gray[(x + 1) * width + y] != HOLLOW_MARK1)
                {
                    gray[(x + 1) * width + y] = HOLLOW_MARK2;
                }
            }
            
            // 左
            if(y > 0)
            {
                if(gray[x * width + y - 1] != HOLLOW_MARK1)
                {
                    gray[x * width + y - 1] = HOLLOW_MARK2;
                }
            }
            
            // 右
            if(y < (width - 1))
            {
                if(gray[x * width + y + 1] != HOLLOW_MARK1)
                {
                    gray[x * width + y + 1] = HOLLOW_MARK2;
                }
            }
        }
    }
}

/**
 * @brief 灰度字模进行镂空操作, 仅保留边框
 * @note  灰度字模, 一个Byte表示一个显示像素
 */
int hollow_out(uint32_t width, uint32_t height, uint8_t *gray)
{
    int i;

    for(i = 0; i < width * height; i++)
    {
        if(gray[i] == HOLLOW_MARK1)
        {
            gray[i] = HOLLOW_MARK3;
        }
    }
}

/**
 * @brief 灰度字模打印接口, 打印到终端方便调试查看
 * @note  灰度字模, 一个Byte表示一个显示像素
 */
int print_number(uint32_t width, uint32_t height, uint8_t *gray)
{
    int i;

    for(i = 0; i < width * height; i++)
    {
        printf("%c", gray[i]);
        if(i % width == (width - 1))
        {
            printf("\n");
        }
    }
    
    printf("-------------------------------------\n");

    return 0;
}

/**
 * @brief 灰度字模转化为ARGB8888字符数组
 * @note  灰度字模, 一个Byte表示一个显示像素
 */
int print_convert(uint32_t width, uint32_t height, uint8_t *gray)
{
    int i;

    for(i = 0; i < width * height; i++)
    {
        if(gray[i] == HOLLOW_MARK1)
        {
            printf("0x%08x, ", 0xFFFFFFFF);
        }
        else if(gray[i] == HOLLOW_MARK2)
        {
            printf("0x%08x, ", 0xFF010101);
        }
        else
        {
            printf("0x%08x, ", 0x00000000);
        }

        if(i % width == (width - 1))
        {
            printf("\n");
        }
    }
    printf("-------------------------------------\n");
    return 0;
}

#define BIG     1
#define MIDDLE  2
#define SMALL   3
#define FONTSIZE MIDDLE

int main()
{
    int width = 0;
    int height = 0;
#if (FONTSIZE == SMALL)
    // uint8_t dot[16] = {0x00,0x00,0xE0,0x0F,0x10,0x10,0x08,0x20,0x08,0x20,0x10,0x10,0xE0,0x0F,0x00,0x00};    /*"0",0*/
    // uint8_t dot[16] = {0x00,0x00,0x10,0x20,0x10,0x20,0xF8,0x3F,0x00,0x20,0x00,0x20,0x00,0x00,0x00,0x00};    /*"1",1*/
    // uint8_t dot[16] = {0x00,0x00,0x70,0x30,0x08,0x28,0x08,0x24,0x08,0x22,0x88,0x21,0x70,0x30,0x00,0x00};    /*"2",2*/
    // uint8_t dot[16] = {0x00,0x00,0x30,0x18,0x08,0x20,0x88,0x20,0x88,0x20,0x48,0x11,0x30,0x0E,0x00,0x00};    /*"3",3*/
     uint8_t dot[16] = {0x00,0x00,0x00,0x07,0xC0,0x04,0x20,0x24,0x10,0x24,0xF8,0x3F,0x00,0x24,0x00,0x00};    /*"4",4*/
    // uint8_t dot[16] = {0x00,0x00,0xF8,0x19,0x08,0x21,0x88,0x20,0x88,0x20,0x08,0x11,0x08,0x0E,0x00,0x00};    /*"5",5*/
    // uint8_t dot[16] = {0x00,0x00,0xE0,0x0F,0x10,0x11,0x88,0x20,0x88,0x20,0x18,0x11,0x00,0x0E,0x00,0x00};    /*"6",6*/
    // uint8_t dot[16] = {0x00,0x00,0x38,0x00,0x08,0x00,0x08,0x3F,0xC8,0x00,0x38,0x00,0x08,0x00,0x00,0x00};    /*"7",7*/
    // uint8_t dot[16] = {0x00,0x00,0x70,0x1C,0x88,0x22,0x08,0x21,0x08,0x21,0x88,0x22,0x70,0x1C,0x00,0x00};    /*"8",8*/
    // uint8_t dot[16] = {0x00,0x00,0xE0,0x00,0x10,0x31,0x08,0x22,0x08,0x22,0x10,0x11,0xE0,0x0F,0x00,0x00};    /*"9",9*/
    // uint8_t dot[16] = {0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x30,0xC0,0x30,0x00,0x00,0x00,0x00,0x00,0x00};    /*":",10*/
    // uint8_t dot[16] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};    /*" ",11*/
    // uint8_t dot[16] = {0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01};    /*"-",12*/
    uint8_t gray[16][8] = { 0 };
    width = 8;
    height = 16;

    /* 点阵字模转化为灰度图片 */
    hollow_dot2gray(width, height, dot, (uint8_t*)gray);
    print_number(width, height, (uint8_t*)gray);

    /* 描边 */
    hollow_border_add(width, height, (uint8_t*)gray);
    print_number(width, height, (uint8_t*)gray);

    /* 镂空 */
    hollow_out(width, height, (uint8_t*)gray);
    print_number(width, height, (uint8_t*)gray);

    /* 灰度图片转化为点阵字模 */
    hollow_gray2dot(width, height, (uint8_t*)gray, dot);
    
    /*===========================================*/
    /* 测试镂空字的点阵字模是否 OK */
    hollow_dot2gray(width, height, dot, (uint8_t*)gray);
    print_number(width, height, (uint8_t*)gray);
#elif (FONTSIZE == MIDDLE)
    // uint8_t dot[64] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x3F,0x00,0x00,0xFE,0xFF,0x01,
                       // 0x00,0x0F,0xC0,0x03,0x80,0x01,0x00,0x06,0xC0,0x00,0x00,0x0C,0x40,0x00,0x00,0x08,
                       // 0x40,0x00,0x00,0x08,0x40,0x00,0x00,0x08,0x80,0x01,0x00,0x06,0x00,0x07,0x80,0x03,
                       // 0x00,0xFE,0xFF,0x01,0x00,0xF0,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};    /*"0",0*/
    uint8_t dot[64] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x08,
                       0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x0C,0x80,0xFF,0xFF,0x0F,
                       0xC0,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x08,
                       0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};    /*"1",1*/
    uint8_t gray[32][16] = { 0 };
    width = 16;
    height = 32;

    /* 点阵字模转化为灰度图片 */
    hollow_dot2gray(width, height, dot, (uint8_t*)gray);
    print_number(width, height, (uint8_t*)gray);

    /* 描边 */
    hollow_border_add(width, height, (uint8_t*)gray);
    print_number(width, height, (uint8_t*)gray);

    /* 镂空 */
    hollow_out(width, height, (uint8_t*)gray);
    print_number(width, height, (uint8_t*)gray);

    /* 灰度图片转化为点阵字模 */
    hollow_gray2dot(width, height, (uint8_t*)gray, dot);
    
    /*===========================================*/
    /* 测试镂空字的点阵字模是否 OK */
    hollow_dot2gray(width, height, dot, (uint8_t*)gray);
    print_number(width, height, (uint8_t*)gray);
#elif (FONTSIZE == BIG)
    uint8_t bigdot[256] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                             0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x3F,0x00,0x00,0x00,0x00,0x00,
                             0x00,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,
                             0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0xC0,0x3F,0x00,
                             0x00,0x78,0x00,0x00,0x00,0xFE,0x7F,0x00,0x00,0x78,0x00,0x00,0xC0,0xFF,0x7F,0x00,0x00,0x78,0x00,0x00,0xF8,0xFF,0x7F,0x00,
                             0x00,0x78,0x00,0x00,0xFE,0xFF,0x7F,0x00,0x00,0x78,0x00,0x80,0xFF,0xFF,0x3F,0x00,0x00,0x78,0x00,0xE0,0x1F,0x00,0x00,0x00,
                             0x00,0x78,0x00,0xFC,0x03,0x00,0x00,0x00,0x00,0x78,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x78,0x80,0x0F,0x00,0x00,0x00,0x00,
                             0x00,0x78,0xE0,0x01,0x00,0x00,0x00,0x00,0x00,0x78,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x1E,0x00,0x00,0x00,0x00,0x00,
                             0x00,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,
                             0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                             0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; /*"7",7*/
    uint8_t biggray[64][32] = { 0 };
    
    width = 32;
    height = 64;

    /* 点阵字模转化为灰度图片 */
    hollow_dot2gray(width, height, bigdot, (uint8_t*)biggray);
    print_number(width, height, (uint8_t*)biggray);

    /* 描边 */
    hollow_border_add(width, height, (uint8_t*)biggray);
    print_number(width, height, (uint8_t*)biggray);

    /* 镂空 */
    hollow_out(width, height, (uint8_t*)biggray);
    print_number(width, height, (uint8_t*)biggray);

    /* 灰度图片转化为点阵字模 */
    hollow_gray2dot(width, height, (uint8_t*)biggray, bigdot);
    
    /*===========================================*/
    /* 测试镂空字的点阵字模是否 OK */
    hollow_dot2gray(width, height, bigdot, (uint8_t*)biggray);
    print_number(width, height, (uint8_t*)biggray);
#endif
    return 0;
}
